package com.webank.maling.base.config;

import com.webank.maling.base.enums.ParseType;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * 应用配置类
 */
@Slf4j
@Data
public class AppConfig {
    private static final AppConfig INSTANCE = new AppConfig();

    // NebulaGraph配置
    private String nebulaHosts;
    private String nebulaUsername;
    private String nebulaPassword;
    private String nebulaSpace;
    private int nebulaConnectionPoolSize;
    private int nebulaTimeout;

    // Milvus配置
    private String milvusUri;
    private String milvusUsername;
    private String milvusPassword;
    private String milvusCollection;
    private int milvusDimension;

    // OpenAI配置
    private String embeddingUrl;
    private String embeddingModel;
    private String embeddingApiKey;

    private String chatUrl;
    private String chatModel;
    private String chatApiKey;

    private String globalLibraryPath;
    private String globalDecompileOutputPath;

    // 项目配置
    private String projectRootPath;
    private String projectId;
    private String branch;
    private String targetPackage;
    private List<String> projectDiscardRegxList;

    private ParseType parseType;

    private AppConfig() {
        loadConfig();
    }

    public static AppConfig getInstance() {
        return INSTANCE;
    }

    private void loadConfig() {
        Properties properties = new Properties();
        try (InputStream input = getClass().getClassLoader().getResourceAsStream("properties/application.properties")) {
            if (input == null) {
                log.error("Unable to find application.properties");
                return;
            }
            try (Reader reader = new InputStreamReader(input, StandardCharsets.UTF_8)) {
                properties.load(reader);
            }

            // 加载NebulaGraph配置
            nebulaHosts = properties.getProperty("nebula.hosts");
            nebulaUsername = properties.getProperty("nebula.username");
            nebulaPassword = properties.getProperty("nebula.password");
            nebulaSpace = properties.getProperty("nebula.space");
            nebulaConnectionPoolSize = Integer.parseInt(properties.getProperty("nebula.connection_pool_size", "10"));
            nebulaTimeout = Integer.parseInt(properties.getProperty("nebula.timeout", "60000"));

            // 加载Milvus配置
            milvusUri = properties.getProperty("milvus.uri");
            milvusUsername = properties.getProperty("milvus.username");
            milvusPassword = properties.getProperty("milvus.password");
            milvusCollection = properties.getProperty("milvus.collection");
            milvusDimension = Integer.parseInt(properties.getProperty("milvus.dimension", "1536"));

            // 加载OpenAI配置
            embeddingModel = properties.getProperty("embedding.model");
            embeddingApiKey = properties.getProperty("embedding.api_key");
            embeddingUrl = properties.getProperty("embedding.url");

            chatModel = properties.getProperty("chat.model");
            chatApiKey = properties.getProperty("chat.api_key");
            chatUrl = properties.getProperty("chat.url");

            globalLibraryPath = properties.getProperty("global.library_path");
            globalDecompileOutputPath = properties.getProperty("global.decompile_output_path");

            // 加载项目配置
            projectRootPath = properties.getProperty("project.root_path");
            if (projectRootPath == null || projectRootPath.isEmpty()) {
                // 如果未指定项目根路径，则使用当前路径
                projectRootPath = Paths.get("").toAbsolutePath().toString();
            }
            projectId = properties.getProperty("project.id");
            targetPackage = properties.getProperty("project.target.package");
            branch = properties.getProperty("project.branch");
            String property = properties.getProperty("project.discard.regx.list");
            projectDiscardRegxList = StringUtils.isBlank(property) ? new ArrayList<>() :
                    new ArrayList<>(List.of(property.split(",")));

            log.info("Configuration loaded successfully");
        } catch (IOException e) {
            log.error("Failed to load application.properties", e);
        } catch (NumberFormatException e) {
            log.error("Invalid number format in configuration", e);
        }
    }

    /**
     * 获取相对于项目根路径的路径
     *
     * @param absolutePath 绝对路径
     * @return 相对路径
     */
    public String getRelativePath(String absolutePath) {
        Path pathAbsolute = Paths.get(absolutePath);
        Path pathBase = Paths.get(projectRootPath);
        return pathBase.relativize(pathAbsolute).toString().replace('\\', '/');
    }

}
